package com.yanqu.road.server.manger;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.enums.eChannelType;
import com.yanqu.road.entity.enums.eServerState;
import com.yanqu.road.entity.servercenter.*;
import com.yanqu.road.logic.bussiness.servercenter.ServerBussiness;
import com.yanqu.road.logic.config.ChannelConfig;
import com.yanqu.road.pb.login.LoginProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ServerListMgr extends TempMgr {

    public static final int SERVER_TYPE_NORMAL = 0;      //普通
    public static final int SERVER_TYPE_REVIEW = 1;      //提审服
    public static final int SERVER_TYPE_DEBUG = 2;       //测试服
    public static final int SERVER_TYPE_ACTIVITY = 3;    //三方活动服

    private static List<ServerInfo> serverList;
    private static Map<Long, ServerInfo> serverInfoMap; // serverList的Map格式
    private static Map<Integer, List<Long>> oldChannelServerIdMap; // serverList的渠道Map格式,更具serverId来的

    private static Map<Long, Map<String, ServerNameLanguage>> serverNameLanguageMap;

    private static Map<Integer, Long> hideTimeMap;

    private static Map<Integer, ChannelInfo> channelInfoMap;

    private static Map<String, AppIdChaneelInfo> appIdChaneelInfoMap;

    private static Map<String, Short> hideJinYuMap;

    // 杂七杂八的多语言 服务器名称 标签 大洲名称等.
    private static Map<String, Map<String, String>> fixedLanguageMap;

    public static int FB_FOLLOW_COUNT = 0;

    public synchronized static int getFbFollowCount() {
        return FB_FOLLOW_COUNT;
    }

    public synchronized static void setFbFollowCount(int fbFollowCount) {
        FB_FOLLOW_COUNT = fbFollowCount;
    }


	public static void addRegisterPreCount(long serverId) {
		ServerInfo serverInfo = getServerInfo(serverId);
		synchronized (serverInfo){
			serverInfo.setPreRoleNum(serverInfo.getPreRoleNum() + 1);
		}
	}

	public static boolean isPreRole(long serverId){
		long nowTime = System.currentTimeMillis();
		ServerInfo serverInfo = getServerInfo(serverId);
		if(serverInfo.isCreatePreRoleOpen() && nowTime/1000 <= serverInfo.getOpenTime()){
			return true;
		}
		return false;
	}

	public static boolean hasPreRoleServer(){
		long nowTime = System.currentTimeMillis();
		for(ServerInfo serverInfo : new ArrayList<>(serverList)){
			if(serverInfo.isCreatePreRoleOpen() && nowTime/1000 <= serverInfo.getOpenTime()){
				return true;
			}
		}
		return false;
	}

	//预创角人数达到上限
	public static boolean isRegisterPreCountMax(long serverId){
		ServerInfo serverInfo = getServerInfo(serverId);
		if(serverInfo.getPreRoleNum() >= serverInfo.getCreatePreRoleNum()){
			return true;
		}
		return false;
	}
	/**
	 * 是否开启fbFollowCount
	 * @return
	 */
	public static boolean isOpenFbFollowCount() {
		int channelId = getServerInfo(ConfigHelper.getLong("serverId")).getChannelId();
		if (channelInfoMap.get(channelId) != null && !StringUtils.isNullOrEmpty(channelInfoMap.get(channelId).getFbFollowUrl())) {
			return true;
		}
		return false;
	}

    public static boolean isOpenTranslateChat() {
        int channelId = getServerInfo(ConfigHelper.getLong("serverId")).getChannelId();
        if (channelInfoMap.get(channelId) != null && !StringUtils.isNullOrEmpty(channelInfoMap.get(channelId).getTranslateUrl())) {
            return true;
        }
        return false;
    }

    @Override
    public boolean stop() {
        return false;
    }

	private static long reloadTime = 0;
	@Override
	public boolean save() {
		boolean isUserCenter = "1".equals(ConfigHelper.getValue("isUserCenter"));
		if(!isUserCenter){
			for(ServerInfo serverInfo : serverList){
				if(serverInfo.isUpdateOption()){
					ServerBussiness.updateServer(serverInfo);
				}
			}
		}
		if(isUserCenter){
			//十秒钟加载一次，要知道注册了多少人
			if(System.currentTimeMillis() - reloadTime > DateHelper.SECOND_MILLIONS * 10){
				List<ServerInfo> tempList = ServerBussiness.getServerInfoList();
				for(ServerInfo data : tempList){
					ServerInfo serverInfo = getServerInfo(data.getServerId());
					if(null != serverInfo){
						serverInfo.setPreRoleNum(data.getPreRoleNum());
					}
				}
				reloadTime = System.currentTimeMillis();
			}
		}
		return false;
	}

    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadData() throws Exception{
        return reloadServerList();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    public static boolean reloadServerList() throws Exception{
        serverList = ServerBussiness.getServerInfoList();
        Map<Long, ServerInfo> tempServerMap = new ConcurrentHashMap<>();
        Map<Integer, List<Long>> tempOldChannelServerIdMap = new ConcurrentHashMap<>();
        for (ServerInfo info : serverList) {
            tempServerMap.put(info.getServerId(), info);
            int oldChannelId = getFirstThreeDigits((int)info.getServerId());
            if(!tempOldChannelServerIdMap.containsKey(oldChannelId)){
                tempOldChannelServerIdMap.put(oldChannelId,new ArrayList<>());
            }
            tempOldChannelServerIdMap.get(oldChannelId).add(info.getServerId());
        }

        serverInfoMap = tempServerMap;
        oldChannelServerIdMap = tempOldChannelServerIdMap;
        serverNameLanguageMap = ServerBussiness.getServerNameLanguageMap();
        appIdChaneelInfoMap = ServerBussiness.getAppIdChannelInfoMap();
        hideTimeMap = ServerBussiness.getHideTimeMap();
        channelInfoMap = ServerBussiness.getChannelListInfo();
        fixedLanguageMap = ServerBussiness.getFixedLanguageMap();
        if (serverList.size() <= 0) {
            return false;
        }
        hideJinYuMap = ServerBussiness.getHideJinYuUserMap();
        return true;
    }

    public static Map<String, Short> getHideJinYuMap() {
        return hideJinYuMap;
    }

    public static Map<String, Map<String, String>> getFixedLanguageMap() {
        return fixedLanguageMap;
    }

    public static String getLanguageFixedName(String srcName, String language) {
        if (fixedLanguageMap.containsKey(srcName) && fixedLanguageMap.get(srcName).containsKey(language)) {
            return fixedLanguageMap.get(srcName).get(language);
        }
        return srcName;
    }

    /**
     * 获取渠道信息
     * @param channelId
     * @return
     */
    public static ChannelInfo getChannelInfo(int channelId) {
        ChannelInfo channelInfo = channelInfoMap.get(channelId);
        return channelInfo;
    }

    /**
     * 通过appid获取渠道号
     * @param appId
     * @return
     */
    public static int getChannelIdByAppId(String appId) {

        AppIdChaneelInfo appIdChaneelInfo = appIdChaneelInfoMap.get(appId);
        if (appIdChaneelInfo == null) {
            return 0;
        }
        return appIdChaneelInfo.getChannelId();
    }

    public static AppIdChaneelInfo getAppIdChaneelInfo(String appId) {
        return appIdChaneelInfoMap.get(appId);
    }


    //是否给的serverId列表在其中
    public static boolean isServerIdIn(Long userServerId,List<Long> serverIdList){
        Map<Long,ServerInfo> serverInfoMap = new ConcurrentHashMap<>();
        for(ServerInfo serverInfo : serverList){
            serverInfoMap.put(serverInfo.getServerId(),serverInfo);
        }
        for(long serverId : serverIdList){
            if(!serverInfoMap.containsKey(serverId)){
                return false;
            }
        }
        //自己的区服没在列表里
        if(!serverIdList.contains(userServerId)){
            return false;
        }
        return true;
    }

    public static List<ServerInfo> getChannelServerList(int channelId, String ip, ChannelVersion channelVersion,String platformUserId) {
        List<ServerInfo> dataList = new ArrayList<>();
        if (WhiteIpMgr.isBlackIp(ip)) {
            if(null != channelVersion) {
                return getBlackIpServerList(channelId, channelVersion.getPhonePlatform());
            }
        } else if(WhiteIpMgr.isPlayerWhiteIp(ip) || PlatformUserIdMgr.isPlatformUserIdPass(platformUserId)){
            dataList = new ArrayList<>(serverList);
        } else {
            if(null != channelVersion) {
                return getChannelServerList(channelId, channelVersion.isReview(), channelVersion.getPhonePlatform(), channelId);
            }
        }
        return dataList;
    }

    public static List<ServerInfo> getPackageServerList(String packageMark, boolean isReview, String ip, String platformUserId,
                                                        int channelId, String appId) {
        List<ServerInfo> dataList = new ArrayList<>();
        if (WhiteIpMgr.isBlackIp(ip)) {
            PackageMark packageMarkData = PackageVersionMgr.getPackageMark(packageMark);
            if(null != packageMarkData) {
                return getBlackIpServerList(channelId, packageMarkData.getPhonePlatform());
            }
        }else if(WhiteIpMgr.isPlayerWhiteIp(ip) || PlatformUserIdMgr.isPlatformUserIdPass(platformUserId)){
            dataList = new ArrayList<>(serverList);
        }else {
            PackageMark packageMarkData = PackageVersionMgr.getPackageMark(packageMark);
            if(null != packageMarkData) {
                int oldChannelId = channelId;
                if(ServerListMgr.is201AppId(appId)){
                    oldChannelId = 201;
                }else if(ServerListMgr.is311AppId(appId)){
                    oldChannelId = 311;
                }
                return getChannelServerList(channelId, isReview, packageMarkData.getPhonePlatform(), oldChannelId);
            }
        }
        return dataList;
    }


    public static int getFirstThreeDigits(int number) {
        int digits = (int) Math.log10(number) + 1;
        int divisor = (int) Math.pow(10, digits - 3);
        int firstThreeDigits = number / divisor;
        return firstThreeDigits;
    }

	/**
	 * 根据提审状态、手机平台获取服务器列表
	 * @param channelId
	 * @param isReview
	 * @param phonePlatform
	 * @return
	 */
	private static List<ServerInfo> getChannelServerList(int channelId, boolean isReview, int phonePlatform, int oldChannelId) {
		List<ServerInfo> dataList = new ArrayList<>();
		if(isReview) {
			for (ServerInfo serverInfo : serverList) {
				if (serverInfo.getChannelId() == channelId) {
					if ((serverInfo.isCreatePreRoleOpen() || isServerOpen(serverInfo)) && SERVER_TYPE_REVIEW == serverInfo.getServerType() &&
							isServerAccessPhonePlatform(serverInfo, phonePlatform)) {
					    if(oldChannelId == 201){
					        if(serverInfo.getServerId() == 20199999){
                                dataList.add(serverInfo);
                            }
                        }else if(oldChannelId == 301){
					        if(serverInfo.getServerId() == 30109999){
                                dataList.add(serverInfo);
                            }
                        }else {
                            dataList.add(serverInfo);
                        }
					}
				}
			}
		}else {
            for (ServerInfo serverInfo : serverList) {
				if (serverInfo.getChannelId() == channelId) {
				     if (channelId == eChannelType.Thailand.getValue() || channelId == eChannelType.UK.getValue() || channelId == eChannelType.US.getValue() || channelId ==  eChannelType.TaiWan.getValue() || channelId ==  eChannelType.InnerChannel.getValue()) {
						if ((isComingSoon(serverInfo) || serverInfo.isCreatePreRoleOpen() || isServerOpen(serverInfo)) && SERVER_TYPE_NORMAL == serverInfo.getServerType() &&
								isServerAccessPhonePlatform(serverInfo, phonePlatform)) {
                            addComposeServer(dataList, oldChannelId, serverInfo);
						}
					} else {
						if ((serverInfo.isCreatePreRoleOpen() || isServerOpen(serverInfo)) && SERVER_TYPE_NORMAL == serverInfo.getServerType() &&
								isServerAccessPhonePlatform(serverInfo, phonePlatform)) {
                            addComposeServer(dataList, oldChannelId, serverInfo);
						}
					}

                } else {

                    // 如果是在显示的区服内 并且是活动服
                    if (serverInfo.getServerType() == SERVER_TYPE_ACTIVITY) {
                        if (CnActivityMgr.isInDestChannelList(channelId, serverInfo.getChannelId())) {
                            dataList.add(serverInfo);
                        }
                    }
                }
            }
        }
        return dataList;
    }

    //311,321渠道的要取哪些区服
    private static void addComposeServer(List<ServerInfo> dataList, int oldChannelId, ServerInfo serverInfo){
        List<Long> oldChannelServerIdList = oldChannelServerIdMap.get(oldChannelId);
        //和渠道311和321都是321
        if(oldChannelId == eChannelType.Mobile_QQ.getValue() || oldChannelId == eChannelType.Mobile_DY.getValue()){
            long openTime = 1690300800;//2023-07-26
            if(oldChannelServerIdList != null && oldChannelServerIdList.contains(serverInfo.getServerId())){
                dataList.add(serverInfo);
            }else{
                if(serverInfo.getOpenTime() > openTime){
                    dataList.add(serverInfo);
                }
            }
        }else if(oldChannelId == eChannelType.MainLand.getValue() || oldChannelId == eChannelType.XiaoChengXu.getValue()){
            long openTime = 1693929600;//2023-09-06
            if(oldChannelServerIdList != null && oldChannelServerIdList.contains(serverInfo.getServerId())){
                dataList.add(serverInfo);
            }else{
                if(serverInfo.getOpenTime() > openTime){
                    dataList.add(serverInfo);
                }
            }
        }else if(oldChannelId == eChannelType.InnerChannel.getValue() || oldChannelId == eChannelType.MainLandInnerTest.getValue()){
//            long openTime = 1689782400;//2023-07-26
//            if(oldChannelServerIdList != null && oldChannelServerIdList.contains(serverInfo.getServerId())){
//                dataList.add(serverInfo);
//            }else{
//                if(serverInfo.getOpenTime() > openTime){
//                    dataList.add(serverInfo);
//                }
//            }
            dataList.add(serverInfo);
        }else{
            dataList.add(serverInfo);
        }
    }

    private static boolean isServerCanSee(ServerInfo serverInfo) {
        long openTime = serverInfo.getOpenTime();
        return 	System.currentTimeMillis() / 1000 + 48 * 3600 > openTime;
    }

    public static boolean isComingSoon(ServerInfo serverInfo) {

        // 国际服不要期待状态
        if (serverInfo.getChannelId() == eChannelType.Thailand.getValue()
                || serverInfo.getChannelId() == eChannelType.ThailandTest.getValue()
                || serverInfo.getChannelId() == eChannelType.ThailandExperience.getValue()
                || serverInfo.getChannelId() == eChannelType.ThailandInnerTest.getValue()
                || serverInfo.getChannelId() == eChannelType.US.getValue()
                || serverInfo.getChannelId() == eChannelType.UK.getValue()) {
            return false;
        }

        long now = System.currentTimeMillis() / 1000;
        long openTime = serverInfo.getOpenTime();
        return now < openTime && (now + 48 * 3600 > openTime) && serverInfo.isOpen();
    }

	/**
	 * 获取黑名单ip的服务器列表
	 * @param channelId
	 * @param phonePlatform
	 * @return
	 */
	private static List<ServerInfo> getBlackIpServerList(int channelId, int phonePlatform){
		List<ServerInfo> dataList = new ArrayList<>();
		for (ServerInfo serverInfo : serverList) {
			if (serverInfo.getChannelId() == channelId) {
				if ((serverInfo.isCreatePreRoleOpen() || isServerOpen(serverInfo)) && SERVER_TYPE_REVIEW == serverInfo.getServerType() &&
						isServerAccessPhonePlatform(serverInfo, phonePlatform)) {
					dataList.add(serverInfo);
				}
			}
		}
		return dataList;
	}

	public static List<ServerInfo> getOpenServerList() {
		List<ServerInfo> serverInfoList = new ArrayList<>();
		for (ServerInfo serverInfo : new ArrayList<>(serverList)) {
			if (isServerOpen(serverInfo)) {
				serverInfoList.add(serverInfo);
			}
		}
		return serverInfoList;
	}

	public static List<ServerInfo> getOpenServerList(int channelId) {
		List<ServerInfo> serverInfoList = new ArrayList<>();
		for (ServerInfo serverInfo : new ArrayList<>(serverList)) {
            if (serverInfo.getChannelId() != channelId) {
                continue;
            }
            if (SERVER_TYPE_NORMAL != serverInfo.getServerType()) {
                continue;
            }
            if (isServerOpen(serverInfo)) {
                serverInfoList.add(serverInfo);
            }
        }
		return serverInfoList;
	}

	/**
	 * 区服是否开放
	 */
	public static boolean isServerOpen(ServerInfo serverInfo) {
		return (serverInfo.isOpen() && serverInfo.getOpenTime() <= (System.currentTimeMillis() / 1000));
	}

    /**
     * 区服是否正常提供服务
     */
    public static boolean isServerProvideServices(long serverId){
        ServerInfo serverInfo = null;
        for(ServerInfo tempServer : new ArrayList<>(serverList)){
            if(tempServer.getServerId() == serverId && isServerOpen(tempServer)){
                serverInfo = tempServer;
                break;
            }
        }
        if(null != serverInfo){
            return (serverInfo.getState() == eServerState.Normal.getValue());
        }
        return false;
    }

    public static boolean canLogin(long serverId, String ip, boolean isAdmin,String platformUserId) {
        ServerInfo serverInfo = getServerInfo(serverId);
        if (serverInfo == null || serverInfo.getState() == 1 || isComingSoon(serverInfo)) {
            // 非白名单或者内部账号 不能进入维护游戏 不能进入期待的区服
            if (!isWhiteUser(ip, isAdmin, platformUserId)) {
                return false;
            }
        }
        return true;
    }

    public static ServerInfo getServerInfo(long serverId) {
        return serverInfoMap.get(serverId);
    }

    public static List<ServerInfo> getServerList() {
        return serverList;
    }

    public static boolean isAllServerOnline(Set<Long> serverSet){
        boolean allOnLine = true;
        for (long serverId : serverSet) {
            ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
            if(serverInfo == null || serverInfo.getState() == 1){
                allOnLine = false;
                break;
            }
        }
        return allOnLine;
    }



    public static int getChannelId(long serverId){
        ServerInfo serverInfo = getServerInfo(serverId);
        if(null != serverInfo){
            return serverInfo.getChannelId();
        }
        return 0;
    }

    public static LoginProto.LoginRespMsg.Builder getLoginResp(int ret){
        LoginProto.LoginRespMsg.Builder loginResp = LoginProto.LoginRespMsg.newBuilder();
        loginResp.setRet(ret);
        int serverId = ConfigHelper.getInt("serverId");
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if (serverInfo != null) {
            loginResp.setClientVer(serverInfo.getClientVerCode());
        }
        return loginResp;
    }

    public static long getHideTime(int channelId) {
        if (hideTimeMap.containsKey(channelId)) {
            return hideTimeMap.get(channelId);
        }
        return 0;
    }

    public static String getServerName(long serverId, String language) {
        ServerInfo serverInfo = getServerInfo(serverId);
        if(null == serverInfo){
            return "";
        }
        if (StringUtils.isNullOrEmpty(language)) {
            return serverInfo.getServerName();
        }

        if (!serverNameLanguageMap.containsKey(serverId)) {
            return serverInfo.getServerName();
        }

        if (!serverNameLanguageMap.get(serverId).containsKey(language)) {
            return serverInfo.getServerName();
        }
        return serverNameLanguageMap.get(serverId).get(language).getServerName();
    }

	public static JSONObject parseServerJson(ServerInfo serverInfo, String language, boolean isMarkStrUrlEncoder, boolean whiteAccount,boolean isCreatePreRole){
		JSONObject serverObj = new JSONObject();
		String serverName = ServerListMgr.getLanguageFixedName(serverInfo.getServerName(), language);
		if (StringUtils.isNullOrEmpty(serverName)) {
			serverName = serverInfo.getServerName();
		}
		serverObj.put("serverId", serverInfo.getServerId());
		try {
			String name = URLEncoder.encode(serverName, "UTF-8");
			serverObj.put("name", name.replace("+", "%20"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			serverObj.put("name", serverName);
		}
		serverObj.put("url", serverInfo.getWebServerUrl());
		serverObj.put("state", (!whiteAccount && isComingSoon(serverInfo))?eServerState.ComingSoon.getValue() : serverInfo.getState());
		serverObj.put("wsIndex", serverInfo.getWsIndex());
		serverObj.put("openTime", serverInfo.getOpenTime());
		//特殊服类型 1卖鱼佬服
		serverObj.put("specialServer", serverInfo.getSpecialServer());
		//是不是可以预创角
		serverObj.put("isPreRole", isPreRole(serverInfo.getServerId()));
		//是不是预创角爆满了
		serverObj.put("isPreRoleFull", serverInfo.getPreRoleNum() >= serverInfo.getCreatePreRoleNum());
		serverObj.put("isCreatePreRole", isCreatePreRole);

		serverObj.put("clientVersion", serverInfo.getClientVerCode());
        serverObj.put("serverType", serverInfo.getServerType());

        String markStr = ServerListMgr.getLanguageFixedName(serverInfo.getMarkStr(), language);
        if(isMarkStrUrlEncoder){
            try {
                markStr = URLEncoder.encode(markStr, "UTF-8");
                serverObj.put("markStr", markStr.replace("+", "%20"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                serverObj.put("markStr", markStr);
            }
        }else {
            serverObj.put("markStr", markStr);
        }
        return serverObj;
    }

    public static Map<Integer, ChannelInfo> getChannelInfoMap() {
        return channelInfoMap;
    }

    /**
     * 渠道是否分流
     * @param channelId
     * @return
     */
    public static boolean isChannelOpenSplitFlow(int channelId) {
        if (channelInfoMap.get(channelId) != null) {
            return channelInfoMap.get(channelId).isOpenSplitFlow();
        }
        return false;
    }

    /**
     * 是否白名单
     * @param ip
     * @param isAdmin
     * @param platformUserId
     * @return
     */
    public static boolean isWhiteUser(String ip, boolean isAdmin, String platformUserId){
        return WhiteIpMgr.isPlayerWhiteIp(ip) || PlatformUserIdMgr.isPlatformUserIdPass(platformUserId) || isAdmin;
    }

    /**
     * 是否可接入手机平台服务器
     * @param serverInfo
     * @param phonePlatform
     * @return
     */
    public static boolean isServerAccessPhonePlatform(ServerInfo serverInfo, int phonePlatform){
        return serverInfo.getAccessPhonePlatform() == 0 || serverInfo.getAccessPhonePlatform() == phonePlatform;
    }

    /**
     * 获取渠道所有区服
     */
    public static List<ServerInfo> getChannelServerList(int channelId) {
        List<ServerInfo> dataList = new ArrayList<>();
        for (ServerInfo serverInfo : new ArrayList<>(serverList)) {
            if (serverInfo.getChannelId() == channelId) {
                dataList.add(serverInfo);
            }
        }
        return dataList;
    }


    public static boolean checkSystemOpenByServerOpenDay(int configDay, long serverId) {
        ServerInfo serverInfo = getServerInfo(serverId);
        if (serverInfo == null) {
            return false;
        }
        long serverOpenTimeMillis = serverInfo.getOpenTime() * DateHelper.SECOND_MILLIONS;
        long timeMillis = DateHelper.getTodayZeroTimeStamp() - DateHelper.getZeroTimeStamp(serverOpenTimeMillis);
        return (timeMillis / DateHelper.DAY_MILLIONS) + 1 >= configDay;
    }

    /**
     * 获取一组区服到某个时间的平均开服天数
     * @param serverList
     * @param endTime s
     * @return
     */
    public static int getAverageOpenDayNum(List<Long> serverList, int endTime) {
        if (serverList.size() <= 0) {
            return 0;
        }
        long sumOpenDayNum = 0;
        for (Long serverId : serverList) {
            ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
            int openTime = DateHelper.getZeroTime((int) serverInfo.getOpenTime());
            int diffTime = Math.max(0, endTime - openTime);
            // 向上取整
            long openDayNum = (diffTime + DateHelper.DAY_SECONDS - 1) / DateHelper.DAY_SECONDS;
            sumOpenDayNum += openDayNum;
        }
        // 平均开服天数
        return (int) sumOpenDayNum / serverList.size();
    }

	/**
	 * 描述：获取服务器开服天数
	 * 作者：zrq
	 * 时间：2022/8/5
	 * 参数：
	 服务器编号
	 * 返回值：开服天数
	 **/
	public static int getServerOpenDay(long serverId) {
		ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
		return getServerOpenDay(serverInfo);
	}

	public static int getServerOpenDay(ServerInfo serverInfo) {
		int openDay = 0;
		if (null != serverInfo) {
			openDay = DateHelper.calc2DateTDOADays(new Date(serverInfo.getOpenTime() * 1000), new Date());
		}
		return openDay;
	}

	/**
	 * 取指定时间的开服天数
	 * @param serverInfo
	 * @param time 毫秒
	 * @return
	 */
	public static int getServerOpenDayByTime(ServerInfo serverInfo, long time) {
		int openDay = 0;
		if (null != serverInfo) {
			openDay = DateHelper.calc2DateTDOADays(new Date(serverInfo.getOpenTime() * 1000), new Date(time));
		}
		return openDay;
	}

    /**
     * appId是否关闭创角
     *
     * @return
     */
    public static boolean isAppIdLimitRegister(String appId) {
        if (StringUtils.isNullOrEmpty(appId)) {
            return false;
        }
        AppIdChaneelInfo appIdChaneelInfo = appIdChaneelInfoMap.get(appId);
        if (appIdChaneelInfo != null && appIdChaneelInfo.isCreateRoleLimit()) {
            return true;
        }

        return false;
    }

    public static String getChangeAppId(String appId){
        if(StringUtils.isNullOrEmpty(appId)){
            return appId;
        }
        String changeAppId = appId;
        if(appId.contains("#")){
            changeAppId = appId.substring(0, appId.indexOf("#"));
        }
        return changeAppId;
    }

    /**
    * 描述：大陆混服的服务器
    * 作者：zrq
    * 时间：2023/9/4
    * 参数：

    * 返回值：
    **/
    public static boolean isCnMergeServer(long serverId){
        if((serverId > 20100000 && serverId <= 20199999) || (serverId > 30100000 && serverId <= 30199999)){
            return true;
        }
        return false;
    }

    public static boolean is201AppId(String appId){
        if(StringUtils.isNullOrEmpty(appId)){
            return false;
        }
        List<String> dataList = StringUtils.stringToStringList(ChannelConfig.APP_CHANNEL_APPID, ";");
        return dataList.contains(appId);
    }

    public static boolean is311AppId(String appId){
        if(StringUtils.isNullOrEmpty(appId)){
            return false;
        }
        List<String> dataList = StringUtils.stringToStringList(ChannelConfig.SQ_CHANNEL_APPID, ";");
        return dataList.contains(appId);
    }

    public static List<ServerInfo> getAllServerList() {
        return new ArrayList<>(serverList);
    }

    public static List<ServerInfo> getSplitFlowServerList(){
        List<ServerInfo> dataList = new ArrayList<>();
        for (ServerInfo serverInfo : new ArrayList<>(serverList)) {
            if (SERVER_TYPE_NORMAL != serverInfo.getServerType()) {
                continue;
            }
            if(!serverInfo.isOpenSplitFlow()){
                continue;
            }
            if (isServerOpen(serverInfo)) {
                dataList.add(serverInfo);
            }
        }
        return dataList;
    }

    public static Map<String, AppIdChaneelInfo> getAppIdChaneelInfoMap() {
        return appIdChaneelInfoMap;
    }


    private static Map<Integer, Integer> fistRoundDaysMap = new HashMap<>();
    static {
        fistRoundDaysMap.put(1, 13);
        fistRoundDaysMap.put(2, 19);
        fistRoundDaysMap.put(3, 18);
        fistRoundDaysMap.put(4, 17);
        fistRoundDaysMap.put(5, 16);
        fistRoundDaysMap.put(6, 15);
        fistRoundDaysMap.put(7, 14);
    }

    /**
     * 获得区服第一轮天数
     * @param serverInfo
     * @return
     */
    public static int getFirstOpenServerDays(ServerInfo serverInfo) {
        if (!serverInfo.isOpen() || serverInfo.getServerType() != ServerListMgr.SERVER_TYPE_NORMAL) {
            return 0;
        }
        if (serverInfo.getChannelId() == eChannelType.TaiWan.getValue()) {
            if (serverInfo.getServerId() < 10100004) {//台服特殊处理
                return 0;
            }
        }
        int weekNum = DateHelper.getTodayWeek(serverInfo.getOpenTime()*1000);//开服那天周几
        int firstRoundDays = fistRoundDaysMap.getOrDefault(weekNum, 0); //第一轮天数
        if(!StringUtils.isNullOrEmpty(ChannelConfig.FIST_ROUND_DAYS)){
            List<String> stringList = StringUtils.stringToStringList(ChannelConfig.FIST_ROUND_DAYS, "\\|");
            for (String s : stringList) {
                List<Integer> list = StringUtils.stringToIntegerList(s, ",");
                if(list.size() == 2 && list.get(0) == weekNum){
                    firstRoundDays = list.get(1);
                    break;
                }
            }
        }
        return firstRoundDays;
    }

    //todo

    /**
     * 轮次=Roundup（（开服天数-第一轮天数-第二轮天数）/21,0）+2
     * @param serverInfo
     * @return
     */
    public static int getServerTurn(ServerInfo serverInfo) {
        if (!serverInfo.isOpen() || serverInfo.getServerType() != ServerListMgr.SERVER_TYPE_NORMAL) {
            return 0;
        }
        if (serverInfo.getChannelId() == eChannelType.TaiWan.getValue()) {
            if (serverInfo.getServerId() < 10100004) {//台服特殊处理
                return 0;
            }
        }

        int openDays = getServerOpenDay(serverInfo);
        int firstOpenServerDays = getFirstOpenServerDays(serverInfo);
        if (openDays <= firstOpenServerDays) {
            return 1;
        }
        int secondRoundDays = 13;//运营说计算固定13 by 王裕
        if (openDays <= firstOpenServerDays + secondRoundDays) {
            return 2;
        }
        int calcValue = BigDecimal.valueOf(openDays - firstOpenServerDays - secondRoundDays).divide(BigDecimal.valueOf(21),8, RoundingMode.DOWN).setScale(0, BigDecimal.ROUND_UP).intValue();
        return calcValue + 2;
    }

    /**
     * 轮次=Roundup（（开服天数-第一轮天数-第二轮天数）/21,0）+2
     * @param serverInfo
     * @param time 毫秒
     * @return
     */
    public static int getServerTurn(ServerInfo serverInfo, long time) {
        if (!serverInfo.isOpen() || serverInfo.getServerType() != ServerListMgr.SERVER_TYPE_NORMAL) {
            return 0;
        }
        if (serverInfo.getChannelId() == eChannelType.TaiWan.getValue()) {
            if (serverInfo.getServerId() < 10100004) {//台服特殊处理
                return 0;
            }
        }

        int openDays = getServerOpenDayByTime(serverInfo, time / 1000);
        int firstOpenServerDays = getFirstOpenServerDays(serverInfo);
        if (openDays <= firstOpenServerDays) {
            return 1;
        }
        int secondRoundDays = 13;//运营说计算固定13 by 王裕
        if (openDays <= firstOpenServerDays + secondRoundDays) {
            return 2;
        }
        int calcValue = BigDecimal.valueOf(openDays - firstOpenServerDays - secondRoundDays).divide(BigDecimal.valueOf(21),8, RoundingMode.DOWN).setScale(0, BigDecimal.ROUND_UP).intValue();
        return calcValue + 2;
    }
}
